package com.hsingh.eclipse.mercury.handlers;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.ui.PlatformUI;

import com.hsingh.eclipse.mercury.extensionpoint.definition.ITask;
import com.hsingh.eclipse.mercury.extensionpoint.definition.ITaskProvider;
import com.hsingh.eclipse.mercury.ui.MercuryDialog;

/**
 * Opens the Mercury dialog {@code MercuryDialog}.
 * 
 * @see org.eclipse.core.commands.IHandler
 * @see org.eclipse.core.commands.AbstractHandler
 */
public class MercuryHandler extends AbstractHandler {
  /**
   * The constructor.
   */
  public MercuryHandler() {}

  /**
   * the command has been executed, so extract extract the needed information
   * from the application context.
   */
  @Override
  public Object execute(ExecutionEvent event) throws ExecutionException {
    IEvaluationContext parentContext = ((IEvaluationContext) event.getApplicationContext()).getParent();

    List<ITask> tasks = getAvailableTasks(parentContext);

    MercuryDialog dialog;
    ExecutionEvent e = new ExecutionEvent(event.getCommand(), event.getParameters(), event.getTrigger(), parentContext);

    dialog = new MercuryDialog(PlatformUI.getWorkbench().getDisplay().getActiveShell(), tasks, e);
    dialog.setTitle("Mercury");
    dialog.setInitialPattern("?");
    dialog.open();

    return null;
  }

  private List<ITask> getAvailableTasks(final IEvaluationContext context) {
    final List<ITask> tasks = new ArrayList<ITask>();
    IConfigurationElement[] config = Platform.getExtensionRegistry()
        .getConfigurationElementsFor(ITaskProvider.POINT_ID);
    try {
      for (IConfigurationElement e : config) {
        final Object o = e.createExecutableExtension("class");
        if (o instanceof ITaskProvider) {

          ISafeRunnable runnable = new ISafeRunnable() {
            @Override
            public void handleException(Throwable exception) {
              System.out.println("Exception in client");
            }

            @Override
            public void run() throws Exception {
              tasks.addAll(((ITaskProvider) o).getTasks(context));
            }
          };
          SafeRunner.run(runnable);
        }
      }
    } catch (CoreException ex) {
      System.out.println(ex.getMessage());
    }

    return tasks;
  }
}
